/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：呼叫中心-系统通用工具封装层
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taiping.cc.application.tools;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据列处理工具类
 * 317 周孝兵
 */
@Slf4j
public final class DataListUtils {

    /**
     * 以分页方式返回数组中的元素
     */
    public static <T> T[] getArrayByPage(T[] array, int pageSize, int pageIndex) {
        // 起始元素的位置
        int startInclusive = pageIndex * pageSize;
        // 截止元素的位置
        int endExclusive = (pageIndex + 1) * pageSize;
        // 总页数
        int totalPage = array.length / pageSize;
        if (array.length % pageSize > 0) {
            totalPage += 1;
        }
        // 返回最后一页的数据
        if (pageIndex >= totalPage - 1) {
            startInclusive = (totalPage - 1) * pageSize;
            return Arrays.copyOfRange(array, startInclusive, array.length);
        }
        // 返回当前页的数据
        return Arrays.copyOfRange(array, startInclusive, endExclusive);
    }

    /**
     * 以分页方式返回数组中的元素
     */
    public static <T> List<T> getListByPage(T[] array, int pageSize, int pageIndex) {
        // 起始元素的位置
        int startInclusive = pageIndex * pageSize;
        // 截止元素的位置
        int endExclusive = (pageIndex + 1) * pageSize;
        // 总页数
        int totalPage = array.length / pageSize;
        if (array.length % pageSize > 0) {
            totalPage += 1;
        }
        // 返回最后一页的数据
        if (pageIndex >= totalPage - 1) {
            startInclusive = (totalPage - 1) * pageSize;
            return Arrays.stream(array, startInclusive, array.length)
                    .collect(Collectors.toList());
        }
        // 返回当前页的数据
        return Arrays.stream(array, startInclusive, endExclusive)
                .collect(Collectors.toList());
    }

    /**
     * 以分页方式返回列表中的元素
     */
    public static <T> List<T> getListByPage(List<T> list, int pageSize, int pageIndex) {
        // 起始元素的位置
        int fromIndex = pageIndex * pageSize;
        // 截止元素的位置
        int toIndex = (pageIndex + 1) * pageSize;
        // 总页数
        int totalPage = list.size() / pageSize;
        if (list.size() % pageSize > 0) {
            totalPage += 1;
        }
        // 返回最后一页的数据
        if (pageIndex >= totalPage - 1) {
            fromIndex = (totalPage - 1) * pageSize;
            return list.subList(fromIndex, list.size());
        }
        // 返回当前页的数据
        return list.subList(fromIndex, toIndex);
    }

    /**
     * 返回列表中前N个元素
     */
    public static <T> List<T> getTopList(List<T> list, int topSize) {
        return list.stream()
                .limit(topSize)
                .collect(Collectors.toList());
    }

    /**
     * 通过java stream api以分页方式返回列表中的元素
     */
    public static <T> List<T> getPageListWithStream(List<T> list, int pageSize, int pageIndex) {
        // 跳过前面N个元素
        int skipSize = pageIndex * pageSize;
        // 总页数
        int totalPage = list.size() / pageSize;
        if (list.size() % pageSize > 0) {
            totalPage += 1;
        }
        // 如果是最后一页，需要重新计算参数`skip-size`的值
        if (pageIndex >= totalPage - 1) {
            skipSize = (totalPage - 1) * pageSize;
        }
        // 返回当前页的数据
        return list.stream()
                .skip(skipSize)
                .limit(pageSize)
                .collect(Collectors.toList());
    }

    /**
     * 将集合切割为若干个想等长度的子集合
     *
     * @param list 集合
     * @param size 子集合的长度
     * @param coll 子集合的集合
     */
    public static <U> void sliceList(List<U> list, int size, List<List<U>> coll) {
        List<U> divList = list.subList(0, Math.min(size, list.size()));
        coll.add(new ArrayList<>(divList));
        divList.clear();
        if (list.size() <= 0) {
            // 将要返回时，这里再设置下list
            list.addAll(coll.stream().flatMap(Collection::stream).collect(Collectors.toList()));
            return;
        }
        sliceList(list, size, coll);
    }

    /**
     * 将Map切割为若干个想等长度的子Map
     *
     * @param entryList Map的键值对列表
     * @param size      子Map的长度
     * @param mapColl   子Map的列表
     */
    public static <K, V> void sliceMap(List<Map.Entry<K, V>> entryList, int size, List<Map<K, V>> mapColl) {
        List<Map.Entry<K, V>> divEntryList = entryList.subList(0, Math.min(size, entryList.size()));
        Map<K, V> subMap = new HashMap<>();
        for (Map.Entry<K, V> subEntry : divEntryList) {
            subMap.put(subEntry.getKey(), subEntry.getValue());
        }
        mapColl.add(subMap);
        divEntryList.clear();
        if (entryList.size() <= 0) {
            entryList.addAll(mapColl.stream().map(Map::entrySet).flatMap(Collection::stream).collect(Collectors.toList()));
            return;
        }
        sliceMap(entryList, size, mapColl);
    }

}
